package com.chartdemo.view;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.TimeChart;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.util.MathHelper;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;

/**
 * 曲线图
 * 
 * @author huangtg
 * 
 */
public class CurveChartView extends View
{
	private static final long HOUR = 3600 * 1000;
	
	private static final long DAY = HOUR * 24;
	
	private static final int HOURS = 24;
	
	/** The zoom buttons background color. */
	private static final int ZOOM_BUTTONS_COLOR = Color.argb(175, 150, 150, 150);
	
	/**
	 * 矩阵
	 */
	private Rect mRect = new Rect();
	
	/**
	 * scan smaller
	 */
	private Bitmap zoomInImage;
	
	/**
	 * scan bigger
	 */
	private Bitmap zoomOutImage;
	
	/**
	 * scan fit
	 */
	private Bitmap fitZoomImage;
	/** The zoom area size. */
	private int zoomSize = 50;
	/** The zoom buttons rectangle. */
	private RectF mZoomR = new RectF();
	
	/**
	 * 画笔
	 */
	private Paint mPaint = new Paint();
	
	/**
	 * TimeChart
	 */
	private TimeChart mChart;
	
	/**
	 * mRenderer
	 */
	private DefaultRenderer renderer;
	
	public CurveChartView(Context context)
	{
		super(context);
		this.init();
	}
	
	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		canvas.getClipBounds(mRect);
		int top = mRect.top;
		int left = mRect.left;
		int width = mRect.width();
		int height = mRect.height();
		if (true)
		{
			top = 0;
			left = 0;
			width = getMeasuredWidth();
			height = getMeasuredHeight();
		}
		mChart.draw(canvas, left, top, width, height, mPaint);
		if (renderer != null && renderer.isZoomEnabled() && renderer.isZoomButtonsVisible())
		{
			mPaint.setColor(ZOOM_BUTTONS_COLOR);
			zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);
			mZoomR.set(left + width - zoomSize * 3, top + height - zoomSize * 0.775f, left + width, top
					+ height);
			canvas.drawRoundRect(mZoomR, zoomSize / 3, zoomSize / 3, mPaint);
			float buttonY = top + height - zoomSize * 0.625f;
			canvas.drawBitmap(zoomInImage, left + width - zoomSize * 2.75f, buttonY, null);
			canvas.drawBitmap(zoomOutImage, left + width - zoomSize * 1.75f, buttonY, null);
			canvas.drawBitmap(fitZoomImage, left + width - zoomSize * 0.75f, buttonY, null);
		}
	}
	
	public void init()
	{
		zoomInImage = BitmapFactory
				.decodeStream(GraphicalView.class.getResourceAsStream("image/zoom_in.png"));
		zoomOutImage = BitmapFactory.decodeStream(GraphicalView.class
				.getResourceAsStream("image/zoom_out.png"));
		fitZoomImage = BitmapFactory
				.decodeStream(GraphicalView.class.getResourceAsStream("image/zoom-1.png"));
		String[] titles = new String[] { "Inside", "Outside" };
		long now = Math.round(new Date().getTime() / DAY) * DAY;
		List<Date[]> x = new ArrayList<Date[]>();
		for (int i = 0; i < titles.length; i++)
		{
			Date[] dates = new Date[HOURS];
			for (int j = 0; j < HOURS; j++)
			{
				dates[j] = new Date(now - (HOURS - j) * HOUR);
			}
			x.add(dates);
		}
		List<double[]> values = new ArrayList<double[]>();
		
		values.add(new double[] { 21.2, 21.5, 21.7, 21.5, 21.4, 21.4, 21.3, 21.1, 20.6, 20.3, 20.2, 19.9,
				19.7, 19.6, 19.9, 20.3, 20.6, 20.9, 21.2, 21.6, 21.9, 22.1, 21.7, 21.5 });
		values.add(new double[] { 1.9, 1.2, 0.9, 0.5, 0.1, -0.5, -0.6, MathHelper.NULL_VALUE,
				MathHelper.NULL_VALUE, -1.8, -0.3, 1.4, 3.4, 4.9, 7.0, 6.4, 3.4, 2.0, 1.5, 0.9, -0.5,
				MathHelper.NULL_VALUE, -1.9, -2.5, -4.3 });
		
		int[] colors = new int[] { Color.GREEN, Color.BLUE };
		PointStyle[] styles = new PointStyle[] { PointStyle.CIRCLE, PointStyle.DIAMOND };
		XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);
		int length = renderer.getSeriesRendererCount();
		for (int i = 0; i < length; i++)
		{
			((XYSeriesRenderer) renderer.getSeriesRendererAt(i)).setFillPoints(true);
		}
		setChartSettings(renderer, "Sensor temperature", "Hour", "Celsius degrees", x.get(0)[0].getTime(),
				x.get(0)[HOURS - 1].getTime(), -5, 30, Color.LTGRAY, Color.LTGRAY);
		renderer.setXLabels(10);
		renderer.setYLabels(10);
		renderer.setShowGrid(true);
		renderer.setXLabelsAlign(Align.CENTER);
		renderer.setYLabelsAlign(Align.RIGHT);
		
		XYMultipleSeriesDataset dataset = buildDateDataset(titles, x, values);
		
		mChart = new TimeChart(dataset, renderer);
	}
	
	/**
	 * Builds an XY multiple series renderer.
	 * 
	 * @param colors the series rendering colors
	 * @param styles the series point styles
	 * @return the XY multiple series renderers
	 */
	protected XYMultipleSeriesRenderer buildRenderer(int[] colors, PointStyle[] styles)
	{
		XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
		setRenderer(renderer, colors, styles);
		return renderer;
	}
	
	protected void setRenderer(XYMultipleSeriesRenderer renderer, int[] colors, PointStyle[] styles)
	{
		renderer.setAxisTitleTextSize(16);
		renderer.setChartTitleTextSize(20);
		renderer.setLabelsTextSize(15);
		renderer.setLegendTextSize(15);
		renderer.setPointSize(5f);
		renderer.setMargins(new int[] { 20, 30, 15, 20 });
		int length = colors.length;
		for (int i = 0; i < length; i++)
		{
			XYSeriesRenderer r = new XYSeriesRenderer();
			r.setColor(colors[i]);
			r.setPointStyle(styles[i]);
			renderer.addSeriesRenderer(r);
		}
	}
	
	/**
	 * Builds an XY multiple time dataset using the provided values.
	 * 
	 * @param titles the series titles
	 * @param xValues the values for the X axis
	 * @param yValues the values for the Y axis
	 * @return the XY multiple time dataset
	 */
	protected XYMultipleSeriesDataset buildDateDataset(String[] titles, List<Date[]> xValues,
			List<double[]> yValues)
	{
		XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
		int length = titles.length;
		for (int i = 0; i < length; i++)
		{
			TimeSeries series = new TimeSeries(titles[i]);
			Date[] xV = xValues.get(i);
			double[] yV = yValues.get(i);
			int seriesLength = xV.length;
			for (int k = 0; k < seriesLength; k++)
			{
				series.add(xV[k], yV[k]);
			}
			dataset.addSeries(series);
		}
		return dataset;
	}
	
	/**
	 * Sets a few of the series renderer settings.
	 * 
	 * @param renderer the renderer to set the properties to
	 * @param title the chart title
	 * @param xTitle the title for the X axis
	 * @param yTitle the title for the Y axis
	 * @param xMin the minimum value on the X axis
	 * @param xMax the maximum value on the X axis
	 * @param yMin the minimum value on the Y axis
	 * @param yMax the maximum value on the Y axis
	 * @param axesColor the axes color
	 * @param labelsColor the labels color
	 */
	protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,
			String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor, int labelsColor)
	{
		renderer.setChartTitle(title);
		renderer.setXTitle(xTitle);
		renderer.setYTitle(yTitle);
		renderer.setXAxisMin(xMin);
		renderer.setXAxisMax(xMax);
		renderer.setYAxisMin(yMin);
		renderer.setYAxisMax(yMax);
		renderer.setAxesColor(axesColor);
		renderer.setLabelsColor(labelsColor);
	}
}
